
Security News
vlt Launches "reproduce": A New Tool Challenging the Limits of Package Provenance
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
exiftool-vendored
Advanced tools
Fast, cross-platform Node.js access to ExifTool.
Best-of-class cross-platform performance and reliability.
Expect an order of magnitude faster performance than other packages.
Proper extraction of
Support for
Robust type definitions of the top 99.5% tags used by over 6,000 different camera makes and models (see an example)
Auditable ExifTool source code (the vendored code is checksum verified)
Automated updates to ExifTool (as new versions come out monthly)
Robust test coverage, performed with supported Node versions on Linux, Mac, & Windows.
yarn add exiftool-vendored
or
npm install --save exiftool-vendored
Note that exiftool-vendored
provides an installation of ExifTool relevant
for your local platform through
optionalDependencies.
You shouldn't include either the exiftool-vendored.exe
or
exiftool-vendored.pl
as direct dependencies to your project.
If you're installing on a minimal Linux distribution, like
Alpine, you may need to install perl
(Γ la "apk add perl
").
See the CHANGELOG for breaking changes since you last updated.
I bump the major version if there's a chance existing code might be affected.
I've been bit too many times by my code breaking when I pull in minor or patch upgrades with other libraries. I think it's better to be pessimistic in code change impact analysis: "over-promise and under-deliver" your breaking-code changes.
When you upgrade to a new major version, please take a bit more care in validating your own systems, but don't be surprised when everything still works.
There are many configuration options to ExifTool, but all values have (more or less sensible) defaults.
Those defaults have been used to create the
exiftool
singleton.
Note that if you don't use the default singleton, you don't need to .end()
it.
// We're using the singleton here for convenience:
const exiftool = require("exiftool-vendored").exiftool
// And to verify everything is working:
exiftool
.version()
.then((version) => console.log(`We're running ExifTool v${version}`))
If the default ExifTool constructor parameters wont' work for you, it's just a class that takes an options hash:
const ExifTool = require("exiftool-vendored").ExifTool
const exiftool = new ExifTool({ taskTimeoutMillis: 5000 })
You should only use the exported default exiftool
singleton, or only create one instance of ExifTool
as a singleton.
Remember to .end()
whichever singleton you use.
ExifTool.read()
returns a Promise to a Tags instance. Note
that errors may be returned either by rejecting the promise, or for less
severe problems, via the errors
field.
All other public ExifTool methods return Promise<void>
, and will reject
the promise if the operation is not successful.
ExifTool has a pretty exhaustive set of error checking, and many "errors" are actually non-fatal warnings about invalid tag structures that seem to be regularly found in otherwise-not-corrupt images.
If we rejected every read
or write
when any error happened, this would
prevent reading and/or writing to otherwise-ok files. To "demote" errors to be
warnings that don't reject the underlying task, you can provide either a
minorErrorsRegExp
, or an
implementation of
rejectTaskOnStderr
.
Either of these parameters are provided to the ExifTool
constructor.
To enable trace, debug, info, warning, or error logging from this library and
the underlying batch-cluster
library,
usesetLogger
. Example
code can be found
here.
ExifTool instances emits events for "startError", "taskError", "endError", "beforeEnd", and "end" that you can register listeners for, using on.
exiftool
.read("path/to/image.jpg")
.then((tags /*: Tags */) =>
console.log(
`Make: ${tags.Make}, Model: ${tags.Model}, Errors: ${tags.errors}`
)
)
.catch((err) => console.error("Something terrible happened: ", err))
Extract the low-resolution thumbnail in path/to/image.jpg
, write it to
path/to/thumbnail.jpg
, and return a Promise<void>
that is fulfilled
when the image is extracted:
exiftool.extractThumbnail("path/to/image.jpg", "path/to/thumbnail.jpg")
Extract the Preview
image (only found in some images):
exiftool.extractPreview("path/to/image.jpg", "path/to/preview.jpg")
Extract the JpgFromRaw
image (found in some RAW images):
exiftool.extractJpgFromRaw("path/to/image.cr2", "path/to/fromRaw.jpg")
Extract the binary value from "tagname" tag in path/to/image.jpg
and write it to dest.bin
(which cannot exist already
and whose parent directory must already exist):
exiftool.extractBinaryTag("tagname", "path/to/file.exf", "path/to/dest.bin")
Note that only a portion of tags are writable. Refer to the documentation and look under the "Writable" column.
If you apply malformed values or ask to write to tags that aren't
supported, the returned Promise
will be rejected.
Only string and numeric primitive are supported as values to the object
Write a comment to the given file so it shows up in the Windows Explorer Properties panel:
exiftool.write("path/to/file.jpg", { XPComment: "this is a test comment" })
Change the DateTimeOriginal, CreateDate and ModifyDate tags (using the AllDates shortcut) to 4:56pm UTC on February 6, 2016:
exiftool.write("path/to/file.jpg", { AllDates: "2016-02-06T16:56:00" })
If you edit a timestamp tag, realize that the difference between the
changed timestamp tag and the GPS value is used by exiftool-vendored
to
infer the timezone.
In other words, if you only edit the CreateDate
and don't edit the GPS
timestamps, your timezone will either be incorrect or missing. See the
section about Dates below for more information.
You may find that some of your images have corrupt metadata, and that writing new dates, or editing the rotation information, for example, fails. ExifTool can try to repair these images by rewriting all the metadata into a new file, along with the original image content. See the documentation for more details about this functionality.
rewriteAllTags
returns a void Promise that will be rejected if there are any
errors.
exiftool.rewriteAllTags("problematic.jpg", "rewritten.jpg")
.ExifTool_config
)ExifTool has an extensive user configuration system. There are several ways to use one:
HOME
directoryEXIFTOOL_HOME
environment variable to the fully-qualified path that
contains your user config.new ExifTool({ exiftoolEnv: { EXIFTOOL_HOME: resolve("path", "to", "config", "dir") }
Always remember to call .end()
.
ExifTool child processes consume system resources. Ensure you don't leave zombie
processes around by calling .end()
, which returns a Promise<void>
if you
want to wait for the shutdown to be complete.
If you use mocha v4 or later, and you don't call
exiftool.end()
, you will find that your test suite hangs. The relevant
change is described here,
and can be solved by adding an after
block that shuts down the instance
of ExifTool that your tests are using:
after(() => exiftool.end()) // assuming your singleton is called `exiftool`
The date metadata in all your images and videos are, most likely, underspecified.
Images and videos rarely specify a time zone in their dates. If all your files were captured in your current time zone, defaulting to the local time zone is a safe assumption, but if you have files that were captured in different parts of the world, this assumption will not be correct. Parsing the same file in different parts of the world results in a different times for the same file.
Prior to version 7, heuristic 1 and 3 was applied.
As of version 7.0.0, exiftool-vendored
uses the following heuristics. The
highest-priority heuristic to return a value will be used as the timezone offset
for all datetime tags that don't already have a specified timezone.
If the EXIF
TimeZoneOffset
tag is present it will be applied as per the spec to
DateTimeOriginal
, and if there are two values, the ModifyDate
tag as well.
OffsetTime
, OffsetTimeOriginal
, and OffsetTimeDigitized
are also
respected, if present (but are very rarely set).
If GPS latitude and longitude is present and valid (the value of 0, 0
is
considered invalid), the tz-lookup
library will be used to determine the time
zone name for that location.
If GPSDateTime
or DateTimeUTC
is present, the delta with the dates found
within the file, as long as the delta is valid, is used as the timezone offset.
Deltas of > 14 hours are considered invalid.
Because datetimes have this optionally-set timezone, and some tags only specify
the date, this library returns classes that encode the date, the time of day, or
both, with an optional timezone and an optional tzoffset: ExifDateTime
and
ExifTime
. It's up to you, then, to determine what's correct for your
situation.
Note also that some smartphones record timestamps with microsecond precision
(not just millis!), and both ExifDateTime
and ExifTime
have floating point
milliseconds.
Official EXIF tag names
are PascalCased, like
AFPointSelected
and ISO
. ("Fixing" the field names to be camelCase, would
result in ungainly aFPointSelected
and iSO
atrocities).
The Tags interface is
auto-generated by the mktags
script, which parses through over 6,000 unique
camera make and model images, in large part sourced from the ExifTool site.
mktags
groups tags, extracts their type, popularity, and example values such
that your IDE can autocomplete.
For an example of a group of tags, see the EXIFTags interface.
Tags marked with "β β β β ", like MIMEType, should be found in most files. Of the several thousand metadata tags, realize less than 50 are found generally. You'll need to do your own research to determine which tags are valid for your uses.
Note that if parsing fails (for, example, a datetime string), the raw string will be returned. Consuming code should verify both existence and type as reasonable for safety.
The npm run mktags
target reads all tags found in a batch of sample images and
parses the results.
Using exiftool-vendored
:
Read 2236 unique tags from 3011 files.
Parsing took 16191ms (5.4ms / file) # win32, core i7, maxProcs 4
Parsing took 27141ms (9.0ms / file) # ubuntu, core i3, maxProcs 1
Parsing took 12545ms (4.2ms / file) # ubuntu, core i3, maxProcs 4
Using the exiftool
npm package takes 7x longer (and doesn't work on Windows):
Reading 3011 files...
Parsing took 85654ms (28.4ms / file) # ubuntu, core i3
Using ExifTool's -stay_open
batch mode means we can reuse a single
instance of ExifTool across many requests, dropping response latency
dramatically as well as reducing system load.
To avoid overwhelming your system, the exiftool
singleton is configured with a
maxProcs
set to a quarter the number of CPUs on the current system (minimally
1); no more than maxProcs
instances of exiftool
will be spawned. If the
system is CPU constrained, however, you may want a smaller value. If you have
very fast disk IO, you may see a speed increase with larger values of
maxProcs
, but note that each child process can consume 100 MB of RAM.
See the CHANGELOG on github.
v11.5.0
ExifDateTime
and ExifDate
no longer accept just a year or year and month.FAQs
Efficient, cross-platform access to ExifTool
The npm package exiftool-vendored receives a total of 17,020 weekly downloads. As such, exiftool-vendored popularity was classified as popular.
We found that exiftool-vendored demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezerβs API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.